local UIAnim = require "widgets/uianim"
local Widget = require "widgets/widget"
local Image = require "widgets/image"
local r = require "rg_util.richtext"
local Stack = require "rg_util.stack"
local Colour = require "rg_util.colour"
local GetCharWidth = require "rg_util.charwidth".GetCharWidth


local Char = Class(Widget, function(self)
	Widget._ctor(self, "char")
	self.inst.entity:AddTextWidget()

	self.bg = self:AddChild(Image("images/ui.xml", "blank.tex"))

	self.colour = {0,0,0,1}
	self.alpha = 1
	self.event = nil
end)

function Char:Init(char, font, size)
	local tw = self.inst.TextWidget
	tw:SetFont(font)
	tw:SetString(char)
	tw:SetSize(size)

	self.bg:SetSize(GetCharWidth(char)*size, size)
end

function Char:SetColour(r,g,b,a)
	self.colour = {r,g,b,a}
end

function Char:SetAlpha(a)
	self.alpha = a
end


------------

local RText = Class(Widget, function(self, kwargs)
	kwargs = kwargs or {}
	Widget._ctor(self, "rtext")

	self.pool = Stack("textpool")
	self.root = self:AddChild(Widget("root"))
	self.chars = {}

	-- configs
	self.linewidth  = kwargs.linewidth or 80 -- 字符数, ascii视为1x0.5, utf-8视为1x1
	self.lineheight = kwargs.lineheight or 1.5
	self.tabsize 	= kwargs.tabsize or 2
	self.alpha 		= kwargs.alpha or 1
	self.colour 	= kwargs.colour or {1,1,1,1}
	self.font 		= kwargs.font or "rgfont"
	self.anchor 	= kwargs.anchor or "LT"
	self.xoffset 	= kwargs.xoffset or 0

	self.regionwidth = 0
	self.regionheight = 0

	self:SetString(kwargs.string)
end)

function RText:SetString(string)
	if string == nil then
		self:Clear()
	else
		if type(string) == "string" then
			string = r(string)
		end
		self:Clear()
		self.string = string
		self:Write()
		self:ReLayout()
	end
end

function RText:Clear()
	self.string = nil
	self.regionwidth = 0
	self.regionheight = 0
	for _,v in ipairs(self.chars) do
		v:Hide()
		self.pool:push(v)
	end
	self.chars = {{}}
end

function RText:Write()
	-- instantiation characters
	local list = self.string:RichText()
	for _, data in ipairs(list)do
		local ui = not self.pool:isEmpty() and self.pool:pop() or Char() 
		ui:Init(data.char, self.font, self.size)
		ui.data = data
		table.insert(self.chars, ui)
		self.root:AddChild(ui)
	end
end

local PUNCS = require"rg_util.utf8".tolist[['.,:;'"!])}?。，！：；】」？、’”]]

local function ispunc(c)
	return table.contains(PUNC, c)
end

local function isnum(c)
	local byte = string.byte(c, 1) 
	return byte >= 48 and byte <= 57 or c == "."
end

local function isalpha(c)
	local byte = string.byte(c, 1)
	return (byte <= 122 and byte >= 97) or (byte <= 90 and byte >= 65)
end

local function iswhitespace(char)
	local byte = string.byte(char)
    return byte == 32 or byte == 9
end

local function isnewline(char)
	local byte = string.byte(char)
    return byte >= 10 and byte <= 13
end

function RText:ReLayout()
	for _, ui in ipairs(self.chars)do
		local data = ui.data
		

